<?php

Raise::load('control.RaiseAjaxArea');
Raise::load('core.datetime.RaiseTimeSpan');
Raise::load('core.datetime.RaiseDateTime');
Raise::load('core.text.RaiseInflector');

/**
 * RaiseTimeAgo class
 * displays date / time ago in a format of '5 days 2 mins ago'
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.control
 * @since 1.2
 */
class RaiseTimeAgo extends RaiseAjaxArea {

    /**
     * The date time to calculate the amount of time ago.
     * @var RaiseDateTime
     */
    private $dateTime;

    /**
     * The number of time span elements to show
     * @var integer
     */
    private $elements = 1;

    /**
     * Flag whether the time ago should update on its own.
     * @var boolean
     */
    private $autoUpdate = false;

    /**
     * The interval in which auto-update will run
     * @var RaiseTimeSpan
     */
    private $updateInterval;

    /**
     * Period of time to show 'moments ago' instead of the actual time
     * @var RaiseTimeSpan
     */
    private $momentsSpan;

    /**
     * Create a new time ago UI element
     * @param RaiseDateTime $dt The RaiseDateTime to calculate the time ago from
     * @param integer $e (optional) Number of time span elements to show. e.g. 2 will show '5 days 2 hours ago', 1 will show '5 days ago'. Defaults to 1
     * @param boolean $u (optional) Set whether the UIControl should auto update itself via AJAX periodically.
     * @param RaiseTimeSpan $m (optional) Period of time to show 'moments ago' instead of the actual time
     */
    public function __construct($dt, $e = 1, $u = false, $m = 5) {
        $this->dateTime = $dt;
        $this->elements = $e;
        $this->autoUpdate = $u;
        $this->updateInterval = new RaiseTimeSpan(30);
        if($m instanceof RaiseTimeSpan){
            $this->momentsSpan = $m;
        }else{
            $this->momentsSpan = new RaiseTimeSpan($m);
        }
        parent::__construct('');
    }

    /**
     * Get or set the date time to calculate the amount of time ago.
     * @return RaiseDateTime
     */
    public function dateTime(){
        return $this->dateTime->raiseClone();
    }

    /**
     * Get or set number of time span elements to show. e.g. 2 will show '5 days 2 hours ago', 1 will show '5 days ago'.
     * @param integer $e (optional) The new number to set to
     * @return integer
     */
    public function elements($e = null){
        if(func_num_args() == 1){
            $this->elements = $e;
        }
        return $this->elements;
    }

    /**
     * Get or set whether the control should auto-update itself via AJAX
     * @param boolean $a (optional) The new value
     * @return boolean
     */
    public function autoUpdate($a = null){
        if(func_num_args() == 1){
            $this->autoUpdate = $a;
        }
        return $this->autoUpdate;
    }

    /**
     * Get or set the interval between each auto-update call
     * @param RaiseTimeSpan $a (optional) The new value
     * @return RaiseTimeSpan
     */
    public function updateInterval($a = null){
        if(func_num_args() == 1){
            if(!($a instanceof RaiseTimeSpan)){
                throw new RaiseInvalidArgumentException('updateInterval requires first parameter to be RaiseTimeSpan');
            }
            $this->updateInterval = $a;
        }
        return $this->updateInterval;
    }

    /**
     * Get or set the amount of time to display 'moments ago' instead of the actual time
     * @param RaiseTimeSpan $m (optional) The new value
     * @return RaiseTimeSpan
     */
    public function momentsSpan($m = null){
        if(func_num_args() == 1){
            if(!($m instanceof RaiseTimeSpan)){
                throw new RaiseInvalidArgumentException('momentsSpan requires first parameter to be RaiseTimeSpan');
            }
            $this->momentsSpan = $m;
        }
        return $this->momentsSpan;
    }

    public function output() {
        $diff = RaiseDateTime::now()->subtract($this->dateTime);
        $m = 0;
        $s = '';
        if($diff->totalSeconds() < $this->momentsSpan->totalSeconds() || $diff->totalSeconds() < 1){
            $s = 'moments ';
        }else{
            if($m < $this->elements && $diff->day() > 0){
                $s .= $diff->day() . ' ' . RaiseInflector::quantify($diff->day(), 'day'). ' ';
                $m++;
            }
            if($m < $this->elements && $diff->hour() > 0){
                $s .= $diff->hour() . ' ' . RaiseInflector::quantify($diff->hour(), 'hour'). ' ';
                $m++;
            }
            if($m < $this->elements && $diff->minute() > 0){
                $s .= $diff->minute() . ' ' . RaiseInflector::quantify($diff->minute(), 'min'). ' ';
                $m++;
            }
            if($m < $this->elements && $diff->second() > 0){
                $s .= $diff->second() . ' ' . RaiseInflector::quantify($diff->second(), 'sec'). ' ';
                $m++;
            }
        }
        $this->content($s . 'ago');
        $o = parent::output();
        if($this->autoUpdate() && !$this->isAjax()){
            $o .= RaiseJavascript::block('window.setInterval(function(){' . $this->ajaxJavascript() . '}, ' . ($this->updateInterval->totalSeconds() * 1000) . ');', true);
        }
        return $o;
    }

}
